home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / comm / term / term34Source.lha / termPickFile.c < prev    next >
C/C++ Source or Header  |  1993-07-16  |  13KB  |  611 lines

  1. /*
  2. **    termPickFile.c
  3. **
  4. **    Simplified file selection routines
  5. **
  6. **    Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12. enum    {    GAD_LIST,GAD_USE,GAD_SELECT,GAD_CANCEL };
  13.  
  14.     /* CreateAllGadgets():
  15.      *
  16.      *    Get them gadgets goin'.
  17.      */
  18.  
  19. STATIC struct Gadget *
  20. CreateAllGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,struct List *List,STRPTR Current,LONG *Index)
  21. {
  22.     struct Gadget        *Gadget;
  23.     struct NewGadget     NewGadget;
  24.     UWORD             Counter = 0;
  25.     struct Node        *Node,
  26.                 *Next;
  27.     BYTE             GotIt = FALSE;
  28.  
  29.     *Index = 0;
  30.  
  31.     Node = List -> lh_Head;
  32.  
  33.     while(!GotIt && (Next = Node -> ln_Succ))
  34.     {
  35.         if(!Stricmp(Node -> ln_Name,Current))
  36.             GotIt = TRUE;
  37.         else
  38.             (*Index)++;
  39.  
  40.         Node = Next;
  41.     }
  42.  
  43.     if(!GotIt)
  44.         *Index = ~0;
  45.  
  46.     SZ_SizeSetup(Window -> WScreen,&UserFont,TRUE);
  47.  
  48.     memset(&NewGadget,0,sizeof(struct NewGadget));
  49.  
  50.     if(Gadget = CreateContext(GadgetList))
  51.     {
  52.         WORD ButtonWidth,ListWidth;
  53.  
  54.         SZ_ResetMaxWidth();
  55.  
  56.         SZ_UpdateMaxWidth(BUTTON_KIND,LocaleString(MSG_GLOBAL_USE_GAD),0,NULL);
  57.         SZ_UpdateMaxWidth(BUTTON_KIND,LocaleString(MSG_TERMPICKFILE_SELECT_GAD),0,NULL);
  58.         SZ_UpdateMaxWidth(BUTTON_KIND,LocaleString(MSG_GLOBAL_CANCEL_GAD),0,NULL);
  59.  
  60.         ButtonWidth = SZ_ResetMaxWidth();
  61.  
  62.         SZ_UpdateMaxWidth(LISTVIEW_KIND,NULL,40,NULL);
  63.  
  64.         ListWidth = SZ_ResetMaxWidth();
  65.  
  66.         if(ListWidth < 3 * ButtonWidth + 2 * InterWidth)
  67.             ListWidth = 3 * ButtonWidth + 2 * InterWidth;
  68.         else
  69.             ButtonWidth = (ListWidth - 2 * InterWidth) / 3;
  70.  
  71.         SZ_SetWidth(ListWidth);
  72.  
  73.         NewGadget . ng_GadgetText    = LocaleString(MSG_TERMPICKFILE_FILE_LIST_GAD);
  74.         NewGadget . ng_GadgetID        = Counter;
  75.         NewGadget . ng_Flags        = PLACETEXT_ABOVE;
  76.  
  77.         GadgetArray[Counter++] = Gadget = CreateGadget(LISTVIEW_KIND,Gadget,&NewGadget,
  78.             SZ_Adjust,        TRUE,
  79.             SZ_AutoWidth,        TRUE,
  80.             SZ_Lines,        10,
  81.             SZ_InterHeight,        0,
  82.  
  83.             GTLV_Labels,        List,
  84.             GTLV_ShowSelected,    NULL,
  85.             GTLV_Selected,        *Index,
  86.         TAG_DONE);
  87.  
  88.         SZ_SetWidth(ButtonWidth);
  89.  
  90.         NewGadget . ng_GadgetText    = LocaleString(MSG_GLOBAL_USE_GAD);
  91.         NewGadget . ng_GadgetID        = Counter;
  92.         NewGadget . ng_Flags        = 0;
  93.  
  94.         GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  95.             SZ_Adjust,    TRUE,
  96.             SZ_AutoWidth,    TRUE,
  97.             SZ_AlignExtra,    TRUE,
  98.             SZ_AlignLeft,    TRUE,
  99.             SZ_AlignBottom,    TRUE,
  100.             SZ_GroupCount,    3,
  101.         TAG_DONE);
  102.  
  103.         NewGadget . ng_GadgetText    = LocaleString(MSG_TERMPICKFILE_SELECT_GAD);
  104.         NewGadget . ng_GadgetID        = Counter;
  105.  
  106.         GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  107.             SZ_Adjust,    TRUE,
  108.             SZ_AutoWidth,    TRUE,
  109.             SZ_GroupNext,    TRUE,
  110.         TAG_DONE);
  111.  
  112.         NewGadget . ng_GadgetText    = LocaleString(MSG_GLOBAL_CANCEL_GAD);
  113.         NewGadget . ng_GadgetID        = Counter;
  114.  
  115.         GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  116.             SZ_Adjust,    TRUE,
  117.             SZ_AutoWidth,    TRUE,
  118.             SZ_GroupNext,    TRUE,
  119.         TAG_DONE);
  120.     }
  121.  
  122.     return(Gadget);
  123. }
  124.  
  125.     /* AddFile(struct List *List,STRPTR Name):
  126.      *
  127.      *    Add another file to the list:
  128.      */
  129.  
  130. STATIC VOID __regargs
  131. AddFile(struct List *List,STRPTR Name)
  132. {
  133.     struct Node *NewNode;
  134.  
  135.     if(NewNode = CreateNode(Name))
  136.     {
  137.         struct Node    *Node,
  138.                 *Next;
  139.         BYTE         GotIt = FALSE;
  140.         LONG         Result;
  141.  
  142.         Node = List -> lh_Head;
  143.  
  144.         while(Next = Node -> ln_Succ)
  145.         {
  146.             if((Result = Stricmp(Name,Node -> ln_Name)) < 0)
  147.             {
  148.                 Insert(List,NewNode,Node -> ln_Pred);
  149.  
  150.                 GotIt = TRUE;
  151.  
  152.                 break;
  153.             }
  154.             else
  155.             {
  156.                     /* Don't add two identical names. */
  157.  
  158.                 if(!Result)
  159.                 {
  160.                     FreeVec(NewNode);
  161.  
  162.                     return;
  163.                 }
  164.             }
  165.  
  166.             Node = Next;
  167.         }
  168.  
  169.         if(!GotIt)
  170.             AddTail(List,NewNode);
  171.     }
  172. }
  173.  
  174.     /* FileMultiScan(struct List *FileList,STRPTR Directory,STRPTR Pattern):
  175.      *
  176.      *    Scan an assignment, also handles multipath assignments.
  177.      */
  178.  
  179. STATIC VOID __regargs
  180. FileMultiScan(struct List *FileList,STRPTR Directory,STRPTR Pattern)
  181. {
  182.     struct DevProc        *DevProc    = NULL;
  183.     struct MsgPort        *FileSysTask    = GetFileSysTask();
  184.     struct FileInfoBlock    *FileInfo;
  185.     UBYTE             MatchBuffer[MAX_FILENAME_LENGTH];
  186.  
  187.     if(ParsePatternNoCase(Pattern,MatchBuffer,MAX_FILENAME_LENGTH) != -1)
  188.     {
  189.             /* Allocate the fileinfo data. */
  190.  
  191.         if(FileInfo = (struct FileInfoBlock *)AllocDosObjectTags(DOS_FIB,TAG_DONE))
  192.         {
  193.                 /* Loop until all assignments are
  194.                  * processed.
  195.                  */
  196.  
  197.             do
  198.             {
  199.                     /* Get the default filesystem task
  200.                      * in case we stumble upon NULL
  201.                      * directory locks.
  202.                      */
  203.  
  204.                 if(DevProc = GetDeviceProc(Directory,DevProc))
  205.                 {
  206.                         /* Set the default filesystem task. */
  207.  
  208.                     SetFileSysTask(DevProc -> dvp_Port);
  209.  
  210.                         /* Check the object type. */
  211.  
  212.                     if(Examine(DevProc -> dvp_Lock,FileInfo))
  213.                     {
  214.                             /* Is it really a directory? */
  215.  
  216.                         if(FileInfo -> fib_DirEntryType > 0)
  217.                         {
  218.                                 /* Scan the directory... */
  219.  
  220.                             while(ExNext(DevProc -> dvp_Lock,FileInfo))
  221.                             {
  222.                                     /* Did we find a file? */
  223.  
  224.                                 if(FileInfo -> fib_DirEntryType < 0)
  225.                                 {
  226.                                         /* Does the name match the template? */
  227.  
  228.                                     if(MatchPatternNoCase(MatchBuffer,FileInfo -> fib_FileName))
  229.                                         AddFile(FileList,FileInfo -> fib_FileName);
  230.                                 }
  231.                             }
  232.                         }
  233.                     }
  234.                 }
  235.                 else
  236.                     break;
  237.             }
  238.             while(DevProc && (DevProc -> dvp_Flags & DVPF_ASSIGN));
  239.  
  240.                 /* Free the fileinfo data. */
  241.  
  242.             FreeDosObject(DOS_FIB,FileInfo);
  243.         }
  244.     }
  245.  
  246.         /* Reset the default filesystem task. */
  247.  
  248.     SetFileSysTask(FileSysTask);
  249.  
  250.         /* Free device process data. */
  251.  
  252.     if(DevProc)
  253.         FreeDeviceProc(DevProc);
  254. }
  255.  
  256.     /* FreeFileList(struct List *List):
  257.      *
  258.      *    Free a list and list contents.
  259.      */
  260.  
  261. STATIC VOID __regargs
  262. FreeFileList(struct List *List)
  263. {
  264.     struct Node    *Node,
  265.             *Next;
  266.  
  267.     Node = List -> lh_Head;
  268.  
  269.     while(Next = Node -> ln_Succ)
  270.     {
  271.         FreeVec(Node);
  272.  
  273.         Node = Next;
  274.     }
  275.  
  276.     FreeVec(List);
  277. }
  278.  
  279.     /* IsAssign(STRPTR Name):
  280.      *
  281.      *    Does a name refer to an assignment?
  282.      */
  283.  
  284. STATIC BYTE __regargs
  285. IsAssign(STRPTR Name)
  286. {
  287.     WORD NameLen    = strlen(Name) - 1;
  288.     BYTE Result    = FALSE;
  289.  
  290.         /* Does it end with a colon? */
  291.  
  292.     if(Name[NameLen] == ':')
  293.     {
  294.         struct DosList *DosList;
  295.  
  296.             /* Lock the list of assignments for reading. */
  297.  
  298.         if(DosList = AttemptLockDosList(LDF_ASSIGNS | LDF_READ))
  299.         {
  300.             STRPTR AssignName;
  301.  
  302.                 /* Scan the list... */
  303.  
  304.             while(DosList = NextDosEntry(DosList,LDF_ASSIGNS))
  305.             {
  306.                     /* Convert the name from icky
  307.                      * BCPL to `C' style string.
  308.                      */
  309.  
  310.                 AssignName = (STRPTR)BADDR(DosList -> dol_Name);
  311.  
  312.                     /* Does the name length match? */
  313.  
  314.                 if(AssignName[0] == NameLen)
  315.                 {
  316.                         /* Does the name itself match? */
  317.  
  318.                     if(!Strnicmp(&AssignName[1],Name,NameLen))
  319.                     {
  320.                         Result = TRUE;
  321.  
  322.                         break;
  323.                     }
  324.                 }
  325.             }
  326.  
  327.                 /* Unlock the list of assignments. */
  328.  
  329.             UnLockDosList(LDF_ASSIGNS | LDF_READ);
  330.         }
  331.     }
  332.  
  333.         /* Return the result. */
  334.  
  335.     return(Result);
  336. }
  337.  
  338.     /* BuildFileList(STRPTR Directory,STRPTR Pattern):
  339.      *
  340.      *    Build a list of files in an assigned directory
  341.      *    matching a certain pattern.
  342.      */
  343.  
  344. STATIC struct List * __regargs
  345. BuildFileList(STRPTR Directory,STRPTR Pattern)
  346. {
  347.     APTR         OldPtr = ThisProcess -> pr_WindowPtr;
  348.     struct List    *FileList = NULL;
  349.     BPTR         NewDir;
  350.  
  351.         /* No DOS requesters, please! */
  352.  
  353.     ThisProcess -> pr_WindowPtr = (APTR)-1;
  354.  
  355.         /* Is the assignment present? */
  356.  
  357.     if(NewDir = Lock(Directory,ACCESS_READ))
  358.     {
  359.             /* Allocate space for the new list. */
  360.  
  361.         if(FileList = (struct List *)AllocVec(sizeof(struct List),MEMF_ANY))
  362.         {
  363.                 /* Initialize the list. */
  364.  
  365.             NewList(FileList);
  366.  
  367.                 /* Will we have to deal with
  368.                  * an assignment or a volume?
  369.                  */
  370.  
  371.             if(IsAssign(Directory))
  372.                 FileMultiScan(FileList,Directory,Pattern);
  373.             else
  374.             {
  375.                 struct FileInfoBlock    *FileInfo;
  376.                 UBYTE             MatchBuffer[MAX_FILENAME_LENGTH];
  377.  
  378.                 if(ParsePatternNoCase(Pattern,MatchBuffer,MAX_FILENAME_LENGTH) != -1)
  379.                 {
  380.                         /* Allocate space for a fileinfo block. */
  381.  
  382.                     if(FileInfo = (struct FileInfoBlock *)AllocDosObjectTags(DOS_FIB,TAG_DONE))
  383.                     {
  384.                             /* Take a look at the assignment. */
  385.  
  386.                         if(Examine(NewDir,FileInfo))
  387.                         {
  388.                                 /* Does it really refer to a directory? */
  389.  
  390.                             if(FileInfo -> fib_DirEntryType > 0)
  391.                             {
  392.                                     /* Examine the whole directory. */
  393.  
  394.                                 while(ExNext(NewDir,FileInfo))
  395.                                 {
  396.                                         /* Is it a file? */
  397.  
  398.                                     if(FileInfo -> fib_DirEntryType < 0)
  399.                                     {
  400.                                         if(MatchPatternNoCase(MatchBuffer,FileInfo -> fib_FileName))
  401.                                             AddFile(FileList,FileInfo -> fib_FileName);
  402.                                     }
  403.                                 }
  404.                             }
  405.                         }
  406.  
  407.                             /* Free the fileinfo data. */
  408.  
  409.                         FreeDosObject(DOS_FIB,FileInfo);
  410.                     }
  411.                 }
  412.             }
  413.  
  414.                 /* Does the list contain any entries? */
  415.  
  416.             if(!FileList -> lh_Head -> ln_Succ)
  417.             {
  418.                 FreeVec(FileList);
  419.  
  420.                 FileList = NULL;
  421.             }
  422.         }
  423.  
  424.             /* Release the lock on the directory. */
  425.  
  426.         UnLock(NewDir);
  427.     }
  428.  
  429.         /* Enable DOS requesters again. */
  430.  
  431.     ThisProcess -> pr_WindowPtr = OldPtr;
  432.  
  433.         /* Return the file name list. */
  434.  
  435.     return(FileList);
  436. }
  437.  
  438.     /* PickFile(STRPTR Directory,STRPTR Pattern,STRPTR Prompt,STRPTR Name):
  439.      *
  440.      *    Your nice file selection routine. No need to hunt for
  441.      *    a library/device by checking all assignments by hand.
  442.      */
  443.  
  444. BYTE
  445. PickFile(STRPTR Directory,STRPTR Pattern,STRPTR Prompt,STRPTR Name)
  446. {
  447.     struct Window        *PanelWindow;
  448.     struct Gadget        *GadgetList = NULL;
  449.     struct Gadget        *GadgetArray[GAD_CANCEL + 1];
  450.     UBYTE              DummyBuffer[MAX_FILENAME_LENGTH],
  451.                 *DummyChar;
  452.     struct FileRequester    *FileRequest;
  453.     struct List        *FileList;
  454.     LONG             Index;
  455.     BYTE             Result = FALSE;
  456.  
  457.     if(!(FileList = BuildFileList(Directory,Pattern)))
  458.     {
  459.         strcpy(DummyBuffer,Name);
  460.  
  461.         DummyChar = PathPart(DummyBuffer);
  462.  
  463.         *DummyChar = 0;
  464.  
  465.         if(FileRequest = GetFile(Prompt,DummyBuffer,FilePart(Name),DummyBuffer,Pattern,FALSE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SELECT_TXT),TRUE))
  466.         {
  467.             if(!Stricmp(FileRequest -> rf_Dir,Directory))
  468.                 strcpy(Name,FileRequest -> rf_File);
  469.             else
  470.                 strcpy(Name,DummyBuffer);
  471.  
  472.             FreeAslRequest(FileRequest);
  473.  
  474.             return(TRUE);
  475.         }
  476.  
  477.         return(FALSE);
  478.     }
  479.  
  480.     if(CreateAllGadgets(GadgetArray,&GadgetList,FileList,Name,&Index))
  481.     {
  482.         if(PanelWindow = OpenWindowTags(NULL,
  483.             WA_Left,    GetScreenLeft(Window) + (GetScreenWidth(Window) - SZ_GetWindowWidth()) / 2,
  484.             WA_Top,        GetScreenTop(Window) + (GetScreenHeight(Window) - SZ_GetWindowHeight())    / 2,
  485.             WA_Width,    SZ_GetWindowWidth(),
  486.             WA_Height,    SZ_GetWindowHeight(),
  487.  
  488.             WA_Activate,        TRUE,
  489.             WA_DragBar,        TRUE,
  490.             WA_DepthGadget,        TRUE,
  491.             WA_RMBTrap,        TRUE,
  492.             WA_CloseGadget,        TRUE,
  493.             WA_CustomScreen,    Window -> WScreen,
  494.             WA_NoCareRefresh,    TRUE,
  495.  
  496.             WA_IDCMP,        IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | IDCMP_ACTIVEWINDOW | LISTVIEWIDCMP | BUTTONIDCMP,
  497.  
  498.             WA_Title,        Prompt,
  499.         TAG_DONE))
  500.         {
  501.             struct IntuiMessage    *Massage;
  502.             ULONG             IClass,Code;
  503.             struct Gadget        *Gadget;
  504.             BYTE             Terminated = FALSE;
  505.  
  506.             PushWindow(PanelWindow);
  507.  
  508.             AddGList(PanelWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
  509.             RefreshGList(GadgetList,PanelWindow,NULL,(UWORD)-1);
  510.             GT_RefreshWindow(PanelWindow,NULL);
  511.  
  512.             if(Index != ~0)
  513.             {
  514.                 GT_SetGadgetAttrs(GadgetArray[GAD_LIST],PanelWindow,NULL,
  515.                     GTLV_Top,        Index,
  516.                     GTLV_MakeVisible,    Index,
  517.                 TAG_DONE);
  518.             }
  519.  
  520.             ClrSignal(SIG_BREAK);
  521.  
  522.             while(!Terminated)
  523.             {
  524.                 if(Wait(PORTMASK(PanelWindow -> UserPort) | SIG_BREAK) & SIG_BREAK)
  525.                     break;
  526.  
  527.                 while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort)))
  528.                 {
  529.                     IClass    = Massage -> Class;
  530.                     Code    = Massage -> Code;
  531.                     Gadget    = (struct Gadget *)Massage -> IAddress;
  532.  
  533.                     GT_ReplyIMsg(Massage);
  534.  
  535.                     KeySelect(GadgetArray,GAD_CANCEL,Code,PanelWindow,&Gadget,&IClass,&Code);
  536.  
  537.                     if(IClass == IDCMP_CLOSEWINDOW)
  538.                         Terminated = TRUE;
  539.  
  540.                     if(IClass == IDCMP_GADGETUP)
  541.                     {
  542.                         switch(Gadget -> GadgetID)
  543.                         {
  544.                             case GAD_USE:
  545.  
  546.                                 if(Index != ~0)
  547.                                 {
  548.                                     struct Node *Node;
  549.  
  550.                                     if(Node = GetListNode(Index,FileList))
  551.                                     {
  552.                                         strcpy(Name,Node -> ln_Name);
  553.  
  554.                                         Result = TRUE;
  555.                                     }
  556.                                 }
  557.  
  558.                                 Terminated = TRUE;
  559.                                 break;
  560.  
  561.                             case GAD_CANCEL:
  562.  
  563.                                 Terminated = TRUE;
  564.                                 break;
  565.  
  566.                             case GAD_LIST:
  567.  
  568.                                 Index = Code;
  569.                                 break;
  570.  
  571.                             case GAD_SELECT:
  572.  
  573.                                 strcpy(DummyBuffer,Name);
  574.  
  575.                                 BlockWindow(PanelWindow);
  576.  
  577.                                 if(FileRequest = GetFile(Prompt,Directory,Name,DummyBuffer,Pattern,FALSE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SELECT_TXT),TRUE))
  578.                                 {
  579.                                     if(!Stricmp(FileRequest -> rf_Dir,Directory))
  580.                                         strcpy(Name,FileRequest -> rf_File);
  581.                                     else
  582.                                         strcpy(Name,DummyBuffer);
  583.  
  584.                                     FreeAslRequest(FileRequest);
  585.  
  586.                                     Terminated = Result = TRUE;
  587.                                 }
  588.  
  589.                                 ReleaseWindow(PanelWindow);
  590.  
  591.                                 break;
  592.                         }
  593.                     }
  594.                 }
  595.             }
  596.  
  597.             RemoveGList(PanelWindow,GadgetList,(UWORD)-1);
  598.  
  599.             PopWindow();
  600.  
  601.             CloseWindow(PanelWindow);
  602.         }
  603.     }
  604.  
  605.     FreeFileList(FileList);
  606.  
  607.     FreeGadgets(GadgetList);
  608.  
  609.     return(Result);
  610. }
  611.